#pragma once

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define PID_PAT		0x00
#define PID_CAT		0x01
#define	PID_TSDT	0x02
#define PID_NIT		0x10
#define PID_SDT		0x11
#define PID_BAT		0x11
#define PID_EIT		0x12
#define	PID_RST		0x13
#define PID_TOT		0x14
#define PID_TDT		0x14

#define TABLE_PAT				0x00
#define TABLE_CAT				0x01
#define TABLE_PMT				0x02
#define TABLE_TSDT				0x03
#define TABLE_NIT_ACTUAL		0x40
#define TABLE_NIT_OTHER			0x41
#define TABLE_SDT_ACTUAL		0x42
#define TABLE_SDT_OTHER			0x46
#define TABLE_BAT				0x4A
#define TABLE_EIT_PF_ACTUAL		0x4E
#define TABLE_EIT_PF_OTHER		0x4F
#define	TABLE_EIT_SC_ACTUAL_ST	0x50
#define	TABLE_EIT_SC_ACTUAL_ED	0x5F
#define	TABLE_EIT_SC_OTHER_ST	0x60
#define	TABLE_EIT_SC_OTHER_ED	0x6F
#define TABLE_TDT				0x70
#define TABLE_RS				0x71	//running status
#define TABLE_SS				0x72	//stuffing
#define TABLE_TOT				0x73

//#define bit	BYTE

typedef enum _TS_Type_
{
	TS_UNKNOWN,
	TS_188 = 188,
	TS_204 = 204
}TS_Type;


class CTSGConfig
{
public:
	CTSGConfig(void);
	~CTSGConfig(void);
	void SetType(TS_Type type);
	TS_Type GetType(void);
	// save the config to the disk
	BOOL SaveConfig(void);
	void SetOffset(SHORT offset);
	SHORT GetOffset(void);

private:
	TS_Type	m_type;
	SHORT m_offset;

};

/*
Class:
Transport Stream Packet
 */
class CTSP
{
public:	
	CTSP(TS_Type type, BYTE* szData);
	~CTSP(void);
	BOOL IsValid(void);
	BYTE IsStartIndicator(void);
	SHORT GetPID(void);
	BOOL HavePayLoad(void);
	BOOL GetPayLoad(BYTE** pPayload, BYTE* nLen);
private:
	CTSP(void);
	CTSP(TS_Type type);
private:	
	TS_Type m_type;
	BYTE* m_szbuf;
	BYTE* m_pPayload;
	BYTE* m_pAdaptionField;
	BYTE m_PayloadLen;
	BYTE m_AdaptionFieldLen;
	SHORT m_PID;
	BOOL m_bValid;
	BYTE m_bStartIndicator;
	BOOL m_bPayload;
};


class CSection
{
public:
	CSection(void);
	~CSection(void);
public:
	SHORT	m_PID;
	BYTE	m_version;
	USHORT	m_parameter;
	BYTE	m_section_number;
	BYTE	m_table_id;
	BYTE*	m_szData;
	SHORT	m_section_length;
	CSection* m_pNext;
};

class CAssemblingSection : public CSection
{
public:
	CAssemblingSection(void);	
	~CAssemblingSection(void);
private:
	CAssemblingSection(CTSP* pTSP);
private:
	SHORT	m_CopyPosition;
	BOOL	m_bComplete;
//operation
public:
	void Format(void);
	BOOL Payload(CTSP* pTSP);
	BOOL IsCompleted(void);
};

class CMpegTable
{
public:
	CMpegTable(void);
	~CMpegTable(void);
	BOOL AddSection(CSection* pAddSection);
	BYTE GetTableId(void);
	CSection* FindSection(CSection* pFindSection);
	CSection* FindSection(USHORT parameter, BYTE version, BYTE section_number);
	virtual BOOL Parser(void) = 0;
private:
	
public:
	CSection* m_pSectionHead;
	CMpegTable* m_pNext;
	//BYTE m_table_id;
};

class CPAT : public CMpegTable
{
public:
	CPAT(void);
	~CPAT(void);
	BOOL Parser(void);
	BOOL Parser(CSection* pSection);
private:
	USHORT	m_transport_stream_id;
};

class CCAT : public CMpegTable
{
public:
	CCAT(void);
	~CCAT(void);
	BOOL Parser(void);	
private:
	USHORT	m_transport_stream_id;
};

class CPMT : public CMpegTable
{
public:
	CPMT(void);
	~CPMT(void);
	BOOL Parser(void);
private:
	USHORT	m_transport_stream_id;
};

class CNIT : public CMpegTable
{
public:
	CNIT(void);
	~CNIT(void);
	BOOL Parser(void);
private:
	USHORT	m_transport_stream_id;
};

class CBAT : public CMpegTable
{
public:
	CBAT(void);
	~CBAT(void);
	BOOL Parser(void);
private:
	USHORT	m_transport_stream_id;
};

class CSDT : public CMpegTable
{
public:
	CSDT(void);
	~CSDT(void);
	BOOL Parser(void);
private:
	USHORT	m_transport_stream_id;
};

class CEIT : public CMpegTable
{
public:
	CEIT(void);
	~CEIT(void);
	BOOL Parser(void);
private:
	USHORT	m_transport_stream_id;
	USHORT	m_service_id;
	USHORT	m_network_id;
};

class CPID
{
public:
	CPID(void);
	~CPID(void);
	CPID(SHORT PID);
//operation
public:
	SHORT GetPID(void);
	CPID* GetNext(void);
	void Attach(CPID* hpid);
	BOOL AddTable(CMpegTable* pAddTable);
	CMpegTable* FindTable(BYTE table_id);
private:
	SHORT m_PID;
	CPID* m_pNext;
public:
	CMpegTable* m_pTableHead;
};


class CTSStatistic
{
public:
	CTSStatistic(void);
	~CTSStatistic(void);
//operation
public:
	BOOL InsertPID(CPID* hpid);
	CPID* FindPID(SHORT pid);
#ifdef _DEBUG
	void Dump(void);
#endif
private:
	CPID* m_hPIDNodeHead;
};

void MpegParserInit(void);
void MpegParserTerm(void);
BOOL RegisterPSIPID(SHORT pid);
BOOL IsPSIPID(SHORT pid);
void AssemblingTSP(CTSP* pTSP, CTSStatistic* pStatistic);
CMpegTable* NewTable(CSection* pSection);